热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

趣味图解|什么是缺页错误PageFault?

来源|后端技术指南针号外号外各位老铁,大家好!最近在想如何让大家在10分钟中有所收获,写一些精悍的知识点。先抛一道阿里面试题给大家热热身&

来源 | 后端技术指南针

号外号外

各位老铁,大家好!

最近在想如何让大家在10分钟中有所收获,写一些精悍的知识点。

先抛一道阿里面试题给大家热热身,引出今天的主角-缺页异常Page Fault。

谈谈对缺页异常Page Fault的理解。

话不多说,集合上车。


术语约定

  • VA:Virtual Address 虚拟地址

  • PA:Physical Address 物理地址

  • MMU:Memory Manage Unit 内存管理单元

  • TLB:Translation Lookaside Buffer 旁路快表缓存/地址变换高速缓存

  • PTE:Page Table Entry 分页表项


内存的惰性分配

以32位的Linux系统为例,每个进程独立拥有4GB的虚拟地址空间,根据局部性原理没有必要也不可能为每个进程分配4GB的物理地址空间。

64位系统也是一样的道理,只不过空间寻址范围大了很多很多倍,进程的虚拟地址空间会分为几个部分:

实际上只有程序运行时用到了才去内存中寻找虚拟地址对应的页帧,找不到才可能进行分配,这就是内存的惰性(延时)分配机制。

对于一个运行中的进程来说,不是所有的虚拟地址在物理内存中都有对应的页,如图展示了部分虚拟地址存在对应物理页的情况:

虚拟地址空间根据固定大小一般是4KB进行划分,物理内存可以设置不同的页面大小,通常物理页大小和虚拟页大小是一样的,本文按照物理页4KB大小展开。

经过前面的分析,我们将面临一个问题:如何将虚拟地址准确快速地映射到物理页呢?

>>>高能预警 敲黑板 本段小结<<<
1. Linux的虚拟地址空间就是空头支票&#xff0c;看着很大但是实际对应的物理空间只有很少的一部分。

2.内存的惰性分配是个有效的机制&#xff0c;可以保证内存利用率和服务器利用率&#xff0c;是资源合理配置的方法。

3.大量的虚拟地址到物理地址的快速准确地查询转换是一个难题。


CPU如果获取内存中的数据

CPU并不直接和物理内存打交道&#xff0c;而是把地址转换的活外包给了MMU&#xff0c;MMU是一种硬件电路&#xff0c;其速度很快&#xff0c;主要工作是进行内存管理&#xff0c;地址转换只是它承接的业务之一。

一起看看MMU是如何搞定地址转换的。


4.1 MMU和Page Table

每个进程都会有自己的页表Page Table&#xff0c;页表存储了进程中虚拟地址到物理地址的映射关系&#xff0c;所以就相当于一张地图&#xff0c;MMU收到CPU的虚拟地址之后开始查询页表&#xff0c;确定是否存在映射以及读写权限是否正常&#xff0c;如图&#xff1a;

对于4GB的虚拟地址且大小为4KB页&#xff0c;一级页表将有2^20个表项&#xff0c;页表占有连续内存并且存储空间大&#xff0c;多级页表可以有效降低页表的存储空间以及内存连续性要求&#xff0c;但是多级页表同时也带来了查询效率问题。

我们以2级页表为例&#xff0c;MMU要先进行两次页表查询确定物理地址&#xff0c;在确认了权限等问题后&#xff0c;MMU再将这个物理地址发送到总线&#xff0c;内存收到之后开始读取对应地址的数据并返回。

MMU在2级页表的情况下进行了2次检索和1次读写&#xff0c;那么当页表变为N级时&#xff0c;就变成了N次检索&#43;1次读写。

可见&#xff0c;页表级数越多查询的步骤越多&#xff0c;对于CPU来说等待时间越长&#xff0c;效率越低&#xff0c;这个问题还需要优化才行。

>> 本段小结 敲黑板 划重点 <<
1.页表存在于进程的内存之中&#xff0c;MMU收到虚拟地址之后查询Page Table来获取物理地址。

2.单级页表对连续内存要求高&#xff0c;于是引入了多级页表&#xff0c;但是多级页表也是一把双刃剑&#xff0c;在减少连续存储要求且减少存储空间的同时降低了查询效率。


4.2 MMU和TLB的故事

MMU和TLB的故事就这样开始了...

CPU觉得MMU干活虽然卖力气&#xff0c;但是效率有点低&#xff0c;不太想继续外包给它了&#xff0c;这一下子把MMU急坏了。

MMU于是找来了一些精通统计的朋友&#xff0c;经过一番研究之后发现CPU用的数据经常是一小搓&#xff0c;但是每次MMU都还要重复之前的步骤来检索&#xff0c;害&#xff0c;就知道埋头干活了&#xff0c;也得讲究方式方法呀&#xff01;

找到瓶颈之后&#xff0c;MMU引入了新武器&#xff0c;江湖人称快表的TLB&#xff0c;别看TLB容量小&#xff0c;但是正式上岗之后干活还真是不含糊。

当CPU给MMU传新虚拟地址之后&#xff0c;MMU先去问TLB那边有没有&#xff0c;如果有就直接拿到物理地址发到总线给内存&#xff0c;齐活。

TLB容量比较小&#xff0c;难免发生Cache Miss&#xff0c;这时候MMU还有保底的老武器页表 Page Table&#xff0c;在页表中找到之后MMU除了把地址发到总线传给内存&#xff0c;还把这条映射关系给到TLB&#xff0c;让它记录一下刷新缓存。

TLB容量不满的时候就直接把新记录存储了&#xff0c;当满了的时候就开启了淘汰大法把旧记录清除掉&#xff0c;来保存新记录&#xff0c;彷佛完美解决了问题。

在TLB和Page Table加持之下&#xff0c;CPU感觉最近MMU比较给力了&#xff0c;就问MMU怎么做到的&#xff1f;MMU就一五一十告诉了CPU。

CPU说是个不错的路子&#xff0c;随后说出了自己的建议&#xff1a;TLB还是有点小&#xff0c;缓存不命中也是经常发生的&#xff0c;要不要搞个大的&#xff0c;这样存储更多访问更快&#xff1f;

MMU一脸苦笑说道大哥TLB很贵的&#xff0c;要不你给涨点外包费&#xff1f;话音未落&#xff0c;CPU就说涨工资是不可能了&#xff0c;这辈子都不可能了。

>>>高能预警 敲黑板 本段小结<<<
1. CPU要根据用户进程提供的虚拟地址来获取真实数据&#xff0c;但是它并不自己做而是交给了MMU。

2. MMU也是个聪明的家伙&#xff0c;集成了TLB来存储CPU最近常用的页表项来加速寻址&#xff0c;TLB找不到再去全量页表寻址&#xff0c;可以认为TLB是MMU的缓存。

3. TLB的容量毕竟有限&#xff0c;为此必须依靠Page Table一起完成TLB Miss情况的查询&#xff0c;并且更新到TLB建立新映射关系。

缺页异常Page Fault大揭秘

设想CPU给MMU的虚拟地址在TLB和Page Table都没有找到对应的物理页帧或者权限不对&#xff0c;该怎么办呢&#xff1f;

没错&#xff0c;这就是缺页异常Page Fault&#xff0c;它是一个由硬件中断触发的可以由软件逻辑纠正的错误。

5.1 PageFault&#xff0c;它来了

假如目标内存页在物理内存中没有对应的页帧或者存在但无对应权限&#xff0c;CPU 就无法获取数据&#xff0c;这种情况下CPU就会报告一个缺页错误。

由于CPU没有数据就无法进行计算&#xff0c;CPU罢工了用户进程也就出现了缺页中断&#xff0c;进程会从用户态切换到内核态&#xff0c;并将缺页中断交给内核的 Page Fault Handler 处理。

缺页异常并不可怕&#xff0c;只要CPU要的虚拟地址经过MMU的一番寻址之后没有找到或者找到后无权限&#xff0c;就会出现缺页异常&#xff0c;因此触发异常后的处理流程将是重点内容。

5.2 缺页错误的分类处理

缺页中断会交给PageFaultHandler处理&#xff0c;其根据缺页中断的不同类型会进行不同的处理&#xff1a;

  • Hard Page Fault
    也被称为Major Page Fault&#xff0c;翻译为硬缺页错误/主要缺页错误&#xff0c;这时物理内存中没有对应的页帧&#xff0c;需要CPU打开磁盘设备读取到物理内存中&#xff0c;再让MMU建立VA和PA的映射。

  • Soft Page Fault
    也被称为Minor Page Fault&#xff0c;翻译为软缺页错误/次要缺页错误&#xff0c;这时物理内存中是存在对应页帧的&#xff0c;只不过可能是其他进程调入的&#xff0c;发出缺页异常的进程不知道而已&#xff0c;此时MMU只需要建立映射即可&#xff0c;无需从磁盘读取写入内存&#xff0c;一般出现在多进程共享内存区域。

  • Invalid Page Fault
    翻译为无效缺页错误&#xff0c;比如进程访问的内存地址越界访问&#xff0c;又比如对空指针解引用内核就会报segment fault错误中断进程直接挂掉。

5.3 缺页错误出现的原因

不同类型的Page Fault出现的原因也不一样&#xff0c;常见的几种原因包括&#xff1a;

  • 非法操作访问越界
    这种情况产生的影响也是最大的&#xff0c;也是Coredump的重要来源&#xff0c;比如空指针解引用或者权限问题等都会出现缺页错误。

  • 使用malloc新申请内存
    malloc机制是延时分配内存&#xff0c;当使用malloc申请内存时并未真实分配物理内存&#xff0c;等到真正开始使用malloc申请的物理内存时发现没有才会启动申请&#xff0c;期间就会出现Page Fault。

  • 访问数据被swap换出
    物理内存是有限资源&#xff0c;当运行很多进程时并不是每个进程都活跃&#xff0c;对此OS会启动内存页面置换将长时间未使用的物理内存页帧放到swap分区来腾空资源给其他进程&#xff0c;当存在于swap分区的页面被访问时就会触发Page Fault从而再置换回物理内存。

>>> 敲黑板 划重点 本段小结&#xff1a;<<<
触发Page Fault的原因可能有很多&#xff0c;归根到底也只有几种大类&#xff1a;

1. 如使用共享内存区域&#xff0c;没有存储VA->PA的映射但是存在物理页帧的软缺页错误&#xff0c;在Page Table/TLB中建立映射关系即可。

2. 访问的地址在物理内存中确实不存在&#xff0c;需要从磁盘/swap分区读入才能使用&#xff0c;这种性能影响会比较大&#xff0c;因为磁盘太慢了&#xff0c;尽量使用高性能的SSD来降低延时。

3. 访问的地址内存非法&#xff0c;缺页错误会升级触发SIGSEGV信号结束进程&#xff0c;这种属于可以导致进程挂掉的一种缺页错误。

全文总结

本文粗浅地和大家一起学习了Page Fault的相关知识点&#xff0c;包括Linux虚拟地址和物理地址的关系、CPU获取内存数据的过程、MMU和TLB&页表的协同配合、缺页异常产生的原因和分类处理。

本文并没有对MMU的内部机制、内核态&用户态缺页异常、缺页异常处理函数等内容进行展开&#xff0c;主要是因为这部分内容相对晦涩&#xff0c;还得靠自己深入研究。

本文旨在把火点燃而不是把桶填满&#xff0c;对于文中相关知识点&#xff0c;欢迎交流沟通学习。

更多精彩推荐
☞一秒带你穿越&#xff01;AI 修复百年前北京影像&#xff0c;路边摊、剃头匠太真实了
☞阿里巴巴副总裁司罗&#xff1a;达摩院如何搭建 NLP 技术体系&#xff1f;
☞可怕&#xff01;如果张东升是个程序员......
☞疫情排查节时86%&#xff1f;不会代码也能玩转模型训练&#xff1f;腾讯大神揭秘语音语义及AutoML黑科技 | 内含福利
☞为了这个技术&#xff0c;操作系统把 CPU 害惨了&#xff01;
☞都在说DeFi&#xff0c;到底什么是DeFi&#xff1f;
你点的每个“在看”&#xff0c;我都认真当成了喜欢


推荐阅读
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
author-avatar
zhongxiaomin1981
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有